package br.com.thor.biblioteca.mensageria.config;

import java.util.HashMap;
import java.util.Map;

public final class Ativador {

	// Cache de refer�ncias a servi�os
	private Map<String, Object> cacheServicos;

	// Singleton
	private static Ativador instancia;

	// Esta classe n�o deve ser instanciada
	private Ativador() throws AtivacaoException {

		try {
			// Inicializo o mapa de cache
			cacheServicos = new HashMap<String, Object>();
		} catch (Exception e) {
			throw new AtivacaoException(e);
		}
	}

	/**
	 * Obtem uma inst�ncia.
	 * 
	 * @return Inst�ncia de <code>Ativador</code>.
	 * @throws AtivacaoException
	 *             Caso ocorra algum problema durante a ativa��o.
	 */
	public static Ativador getInstance() throws AtivacaoException {
		if (instancia == null) {
			instancia = new Ativador();
		}
		return instancia;
	}

	/**
	 * Ativa uma inst�ncia de um servi�o conhecido.
	 * 
	 * @param <T>
	 *            Tipo do servi�o conhecido.
	 * @param classe
	 *            Classe que descreve o servi�o requisitado.
	 * @return Inst�ncia do servi�o solicitado.
	 * @throws AtivacaoException
	 *             Caso ocorra algum problema durante a ativa��o.
	 */
	@SuppressWarnings("unchecked")
	public static <T> T get(Class<T> classe) throws AtivacaoException {
		// Garanto a existência de uma instância
		Ativador instancia = getInstance();
		try {

			// Possuo este servi�o no cache?
			String nomeClasse = classe.getCanonicalName();
			if (!instancia.cacheServicos.containsKey(nomeClasse)) {
				// FIXME (Sem EJB) se o nome possuir "IServico", troco por
				// "Servico"
				instancia.cacheServicos
						.put(nomeClasse,
								Class.forName(
										nomeClasse.replace("IServico",
												"Servico")).newInstance());
			}
			return (T) instancia.cacheServicos.get(nomeClasse);
		} catch (Exception e) {
			throw new AtivacaoException(e);
		}
	}
}
